package com.htfyun.ft.fragment.factory;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.htfyun.ft.R;
import com.htfyun.ft.config.FTBuildConfig;
import com.htfyun.ft.utils.DebugLog;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;

public class FragmentBluetooth extends FactoryBaseFragment {

    private TextView txtStatus;
    private TextView txtBTDiscoveryStatus;
    private TextView txtAutoTestSSID;

    private ListView listView;
    private DeviceAdapter deviceAdapter;

    private SwipeRefreshLayout mSwipeLayout;

    private BluetoothAdapter bluetoothAdapter;


    private Map<String, BTDeviceWithRSSI> bluetoothDeviceMap = new HashMap<>();
    @Override
    protected int getLayoutRes() {
        return R.layout.fragment_factory_bluetooth;
    }

    @Override
    protected void onInitView(@Nullable Bundle savedInstanceState) {
        super.onInitView(savedInstanceState);

        mSwipeLayout = (SwipeRefreshLayout) findViewById(R.id.swipeRefreshLayout);

        mSwipeLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                bluetoothDeviceMap.clear();
                updateDeviceList();

            }
        });

        txtStatus = (TextView) findViewById(R.id.txtStatus);
        txtAutoTestSSID = (TextView) findViewById(R.id.txtAutoTestSSID);
        txtAutoTestSSID.setText((R.string.test_scan_bt_ssid));
        txtStatus.setText("");
        txtBTDiscoveryStatus = (TextView) findViewById(R.id.txtBTDiscoveryStatus);
        txtBTDiscoveryStatus.setText("");

        listView = (ListView) findViewById(R.id.listView);
        deviceAdapter = new DeviceAdapter(getContext(), -1);
        listView.setAdapter(deviceAdapter);

        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (bluetoothAdapter == null) {

            Toast.makeText(getContext(), R.string.test_bt_unsupported, Toast.LENGTH_LONG).show();
            finishMeWithPassed(false);
        }

        setBtnPassVisibility(View.GONE);

    }

    @Override
    protected void onVisible() {
        super.onVisible();

        bluetoothDeviceMap.clear();

        registerBTReceiver();

        startDiscovery();

    }

    @Override
    protected void onInvisible() {
        super.onInvisible();

        unregisterBTReceiver();
    }

    private void startDiscovery() {

        int statusResId = R.string.bt_status_on;

        if (bluetoothAdapter.isEnabled()) {
            bluetoothAdapter.startDiscovery();
        } else {
            bluetoothAdapter.enable();
            statusResId = R.string.bt_status_off;
        }

        txtStatus.setText(getString(R.string.test_bt_status, getString(statusResId)));

    }

    private synchronized void updateDeviceList() {
        deviceAdapter.setNotifyOnChange(false);
        deviceAdapter.clear();

        Collection<BTDeviceWithRSSI> all = bluetoothDeviceMap.values();
        List<BTDeviceWithRSSI> list = new ArrayList<>(all);
        Collections.sort(list);

        deviceAdapter.setNotifyOnChange(true);
        deviceAdapter.addAll(list);

    }

    private volatile boolean isRegistered = false;

    private synchronized void registerBTReceiver() {
        if (getActivity() == null) {
            return;
        }

        if (isRegistered) {
            return;
        }
        isRegistered = true;

        getActivity().registerReceiver(BTReceiver, getIntentFilterOfBT());
    }

    private synchronized void unregisterBTReceiver() {
        if (getActivity() == null) {
            return;
        }

        if (!isRegistered) {
            return;
        }
        isRegistered = false;

        getActivity().unregisterReceiver(BTReceiver);
    }

    private IntentFilter getIntentFilterOfBT() {
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
        intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
        intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
        return intentFilter;
    }

    private BroadcastReceiver BTReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            if (action == null) {
                return;
            }

            if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {

                String stateExtra = BluetoothAdapter.EXTRA_STATE;
                int state = intent.getIntExtra(stateExtra, -1);
                int statusResId = R.string.bt_status_unknown;

                switch(state) {
                    case BluetoothAdapter.STATE_TURNING_ON:
                        statusResId = R.string.bt_status_turning_on;
                        break;
                    case BluetoothAdapter.STATE_ON:
                        statusResId = R.string.bt_status_on;
                        bluetoothAdapter.startDiscovery();
                        break;
                    case BluetoothAdapter.STATE_TURNING_OFF:
                        statusResId = R.string.bt_status_turning_off;
                        bluetoothAdapter.cancelDiscovery();
                        break;
                    case BluetoothAdapter.STATE_OFF:
                        statusResId = R.string.bt_status_off;
                        break;
                }

                txtStatus.setText(getString(R.string.test_bt_status, getString(statusResId)));

            } else if (action.equals(BluetoothAdapter.ACTION_DISCOVERY_STARTED)) {
                txtBTDiscoveryStatus.setText(getString(R.string.test_bt_discovery_status, getString(R.string.bt_discovery_status_doing)));
            } else if (action.equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)) {
                txtBTDiscoveryStatus.setText(getString(R.string.test_bt_discovery_status, getString(R.string.bt_discovery_status_done)));
                getHandler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        if (bluetoothAdapter.isEnabled()) {
                            bluetoothAdapter.startDiscovery();
                        }
                    }
                }, 2 * 1000);
            } else if (action.equals(BluetoothDevice.ACTION_FOUND)) {

                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);


                if (device != null) {

                    DebugLog.e("found device = " + device.getAddress());

                    short rssi = -1;
                    if (intent.getExtras() != null) {
                        rssi = intent.getExtras().getShort(BluetoothDevice.EXTRA_RSSI);
                    }
                    BTDeviceWithRSSI btDeviceWithRSSI = bluetoothDeviceMap.get(device.getAddress());
                    if (btDeviceWithRSSI == null) {
                        btDeviceWithRSSI = new BTDeviceWithRSSI(device, rssi);
                        bluetoothDeviceMap.put(device.getAddress(), btDeviceWithRSSI);
                    }
                    btDeviceWithRSSI.rssi = rssi;
                    String name = device.getName();
                    if (!TextUtils.isEmpty(name) /*&& name.equals(FTBuildConfig.BT_NAME_PASSED)*/
                            && rssi > FTBuildConfig.BT_RSSI_MIN ) {

                        delayAutoPass();

                    }

                    updateDeviceList();

                    mSwipeLayout.setRefreshing(false);

                }

            }
        }
    };

    private class DeviceAdapter extends ArrayAdapter<BTDeviceWithRSSI> {

        public DeviceAdapter(@NonNull Context context, int resource) {
            super(context, resource);
        }

        @NonNull
        @Override
        public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
            ViewHolder holder = null;
            if (convertView != null) {
                holder = (ViewHolder) convertView.getTag();
            }
            if (holder == null) {
                holder = new ViewHolder();
                LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                convertView = inflater.inflate(R.layout.item_bt_devices, null);
                holder.txtName = (TextView) convertView.findViewById(R.id.txtName);
                holder.txtRSSI = (TextView) convertView.findViewById(R.id.txtRSSI);

                convertView.setTag(holder);
            }

            BTDeviceWithRSSI btDeviceWithRSSI = getItem(position);

            if (btDeviceWithRSSI != null) {

                String name = btDeviceWithRSSI.device.getName();
                if (TextUtils.isEmpty(name)) {
                    name = btDeviceWithRSSI.device.getAddress();
                }
                holder.txtName.setText(name);
                holder.txtRSSI.setText(Short.toString(btDeviceWithRSSI.rssi));

            }

            return convertView;
        }
    }

    private final class ViewHolder {

        private TextView txtName;
        private TextView txtRSSI;
    }

    private final class BTDeviceWithRSSI implements Comparable<BTDeviceWithRSSI> {
        BluetoothDevice device;
        short rssi;

        public BTDeviceWithRSSI(BluetoothDevice device, short rssi) {
            this.device = device;
            this.rssi = rssi;
        }


        @Override
        public int compareTo(@NonNull BTDeviceWithRSSI o) {
            return this.rssi - o.rssi;
        }
    }



}
